#include "loader.h"

#include "mmu.h"
#include "tss.h"
#include "klib.h"
#include "gdt.h"
#include "i386.h"

extern unsigned int cr3usu;

void inicializar_gdt_tarea(int indice){
		gdt[GDT_TASK_INI+indice].limit_0_15 = 0x67;
		gdt[GDT_TASK_INI+indice].base_0_15 = (((unsigned int)&(tsss[indice])) & 0x0000ffff);
		gdt[GDT_TASK_INI+indice].base_23_16 = (((unsigned int)&(tsss[indice])) & 0x00ff0000) >> 16;
		gdt[GDT_TASK_INI+indice].type = 0x9;
		gdt[GDT_TASK_INI+indice].s = 0;
		gdt[GDT_TASK_INI+indice].dpl = (indice==0)? 0 : 3;
		gdt[GDT_TASK_INI+indice].p = 1;
		gdt[GDT_TASK_INI+indice].limit_16_19 = 0;
		gdt[GDT_TASK_INI+indice].avl = 1;
		gdt[GDT_TASK_INI+indice].l = 0;
		gdt[GDT_TASK_INI+indice].db = 1;
		gdt[GDT_TASK_INI+indice].g = 0;
		gdt[GDT_TASK_INI+indice].base_31_24 = (((unsigned int)&(tsss[indice])) & 0xff000000) >> 24;	
}

void cargar_tarea(unsigned int desde, unsigned int indice) {
	unsigned int pila_usu = 0;
	unsigned int *ptr_desde = (unsigned int*) desde;
	unsigned int *ptr_cod_usu1 = 0;
	unsigned int *ptr_cod_usu2 = 0;
	
	unsigned int pila_kernel = 0;
	unsigned int i;
	
	if(indice==0){
		inicializar_gdt_tarea(indice);
		return;
	}
	
	//item 1
	pila_usu = (unsigned int)pagina_libre_usuario();
	ptr_cod_usu1 = pagina_libre_usuario();
	ptr_cod_usu2 = pagina_libre_usuario();
	
	//item 2
	pila_kernel = (unsigned int)pagina_libre_kernel();
	
	//item 3
	cr3usu = (unsigned int)inicializar_dir_usuario();
	
	//item 4
	mapear_pagina(0x0,cr3usu,(unsigned int)ptr_cod_usu1,0x00000007);
	mapear_pagina(0x1000,cr3usu,(unsigned int)ptr_cod_usu2,0x00000007);
	mapear_pagina(pila_usu,cr3usu,pila_usu,0x00000007);
	mapear_pagina(pila_kernel,cr3usu,pila_kernel,0x00000003);
	
	//item 5
	for(i=0;i<1024;i++){
		ptr_cod_usu1[i] = ptr_desde[i];
		ptr_cod_usu2[1024+i] = ptr_desde[1024+i];
	}
	
       	//item 6
	tsss[indice].ptl = 0x00;
	tsss[indice].unused0 = 0x00;
	tsss[indice].esp0 = (unsigned int) pila_kernel+0x1000;
	tsss[indice].ss0 = 0x10;   // segmento de datos del kernel
	tsss[indice].unused1 = 0x00;
	tsss[indice].esp1 = 0x0000;
	tsss[indice].ss1 = 0x00;
	tsss[indice].unused2 = 0x00;
	tsss[indice].esp2 = 0x0000;
	tsss[indice].ss2 = 0x00;
	tsss[indice].unused3 = 0x00;
	tsss[indice].cr3 = cr3usu;
	tsss[indice].eip = 0x0;	
	tsss[indice].eflags = 0x202;
	tsss[indice].eax = 0x0000;
	tsss[indice].ecx = 0x0000;
	tsss[indice].edx = 0x0000;
	tsss[indice].ebx = 0x0000;
	tsss[indice].esp = (unsigned int) pila_usu + 0x1000;
	tsss[indice].ebp = 0x0000;	// la pila crece hacia abajo.
	tsss[indice].esi = 0x0000;
	tsss[indice].edi = 0x0000;
	tsss[indice].es = 0x28 | 0x03;		// seg datos, gpl = 3
	tsss[indice].unused4 = 0x00;
	tsss[indice].cs = 0x20 | 0x03;		// seg codigo, gpl = 3
	tsss[indice].unused5 = 0x00;
	tsss[indice].ss = 0x28 | 0x03;		// seg datos, gpl = 3
	tsss[indice].unused6 = 0x00;
	tsss[indice].ds = 0x28 | 0x03;
	tsss[indice].unused7 = 0x00;
	tsss[indice].fs = 0x28 | 0x03;
	tsss[indice].unused8 = 0x00;
	tsss[indice].gs = 0x28 | 0x03;
	tsss[indice].unused9 = 0x00;
	tsss[indice].ldt = 0x00;
	tsss[indice].unused10 = 0x00;
	tsss[indice].dtrap = 0x00;
	tsss[indice].iomap = 0x00;	

	//item 7
	inicializar_gdt_tarea(indice);

}
